# This example shows an implementation of the mathematical
# factorial function (! function) to find the factorial value of !7 = 5040.
.data
argument: .word 7
str1: .string "Factorial value of "
str2: .string " is "
.text
main:
lw a0, argument # Load argument from static data
jal ra, fact # Jump-and-link to the 'fact' label
# Print the result to console
mv a1, a0
lw a0, argument
jal ra, printResult
# Exit program
li a7, 10
ecall
fact:
addi sp, sp, -16
sw ra, 8(sp)
sw a0, 0(sp)
addi t0, a0, -1
bge t0, zero, nfact
addi a0, zero, 1
addi sp, sp, 16
jr x1
nfact:
addi a0, a0, -1
jal ra, fact
addi t1, a0, 0
lw a0, 0(sp)
lw ra, 8(sp)
addi sp, sp, 16
mul a0, a0, t1
ret
# --- printResult ---
# a0: Value which factorial number was computed from
# a1: Factorial result
printResult:
mv t0, a0
mv t1, a1
la a0, str1
li a7, 4
ecall
mv a0, t0
li a7, 1
ecall
la a0, str2
li a7, 4
ecall
mv a0, t1
li a7, 1
ecall
ret
這段c code 是一個在 RISC-V 上實作數學 階乘函數(factorial function)的範例,目標是計算 7 的階乘(即 7! = 5040),並將結果輸出到控制台。以下是分步解釋:
這個部分定義了靜態資料,包括要計算的參數和一些字串:
argument: 定義要計算階乘的數字,這裡是 7。str1: 定義字串 "Factorial value of "。str2: 定義字串 " is "。這裡是實際的程式碼,包括主程式 main,階乘計算函數 fact,以及結果輸出的 printResult。
main)lw a0, argument: 從資料區段載入 argument,即要計算的數字 7,並存入暫存器 a0。jal ra, fact: 跳到 fact 標籤,開始計算階乘,並將返回地址存入 ra 暫存器。mv a1, a0: 把階乘計算結果從 a0 移動到 a1,這是為了後續輸出。lw a0, argument: 再次載入 argument,為了在輸出時顯示原始數字。jal ra, printResult: 跳到 printResult 函數進行結果輸出。li a7, 10: 設定 a7 暫存器為 10,這是系統呼叫的代碼,用於退出程式。ecall: 執行系統呼叫,退出程式。fact)這裡是計算階乘的遞迴函數。
addi sp, sp, -16: 將堆疊指標 sp 向下移動 16 字節,為儲存資料預留空間。sw ra, 8(sp): 將返回地址 ra 存入堆疊。sw a0, 0(sp): 將目前的參數 a0(即階乘的值)存入堆疊。addi t0, a0, -1: 將 a0 減去 1,存入暫存器 t0,準備比較。bge t0, zero, nfact: 如果 t0 大於或等於 0,跳到 nfact,否則返回 1(表示遞迴結束)。如果數字小於等於 1,則返回 1:
addi a0, zero, 1: 將 a0 設為 1。addi sp, sp, 16: 將堆疊指標 sp 恢復。jr x1: 返回主程式。nfact)處理當 a0 > 1 的情況:
addi a0, a0, -1: 將 a0 減去 1。jal ra, fact: 再次呼叫 fact 函數,進行遞迴。addi t1, a0, 0: 將結果存入 t1 暫存器。lw a0, 0(sp): 從堆疊中取回原本的參數。lw ra, 8(sp): 從堆疊中取回返回地址。addi sp, sp, 16: 將堆疊指標 sp 恢復。mul a0, a0, t1: 計算階乘結果(a0 = a0 * t1)。ret: 返回主程式。printResult 函數負責將計算結果輸出到控制台:
a0,然後通過 ecall 系統呼叫輸出:
將編寫RISC-V彙編程式(RV32I ISA)並透過環境呼叫輸出到控制台。